package com.atm.thirdplt.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.atm.thirdplt.common.core.domain.AjaxResult;
import com.atm.thirdplt.common.core.domain.his.AtmHisConfig;
import com.atm.thirdplt.common.core.domain.his.AtmHisMaterial;
import com.atm.thirdplt.common.core.domain.his.TestPriceList;
import com.atm.thirdplt.common.core.domain.his.TestWriteHis;
import com.atm.thirdplt.dao.mapper.his.AtmHisConfigMapper;
import com.atm.thirdplt.dao.mapper.his.AtmHisMaterialMapper;
import com.atm.thirdplt.dao.mapper.his.TestPriceListMapper;
import com.atm.thirdplt.dao.mapper.his.TestWriteHisMapper;
import com.atm.thirdplt.service.AtmHisConfigService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * (AtmHisConfig)表服务实现类
 *
 * @author：makejava
 * @date：2021/08/26
 */
@Slf4j
@Service("/atmHisConfigService")
public class AtmHisConfigServiceImpl implements AtmHisConfigService {

    @Autowired
    private AtmHisConfigMapper atmHisConfigMapper;

    @Autowired
    private AtmHisMaterialMapper atmHisMaterialMapper;

    @Autowired
    private TestPriceListMapper testPriceListMapper;

    @Autowired
    private TestWriteHisMapper testWriteHisMapper;

    /**
     * HisItemClass 去获取配置文件
     *
     * @return
     */
    @Override
    public Map<String, AtmHisConfig> listHisConfigMap() {
        List<AtmHisConfig> list = atmHisConfigMapper.listHisConfigMap();
        Map<String, AtmHisConfig> collect = list.stream().collect(Collectors.toMap(AtmHisConfig::getHisItemClass, Function.identity()));
        return collect;
    }

    /**
     * 写入his 中间表
     *
     * @param testWriteHis
     * @return
     */
    @Transactional
    @Override
    public AjaxResult addWriteHis(List<TestWriteHis> testWriteHis) {
        if (CollUtil.isEmpty(testWriteHis)) {
            return AjaxResult.success();
        }
        TestWriteHis testWriteHis1 = testWriteHis.get(0);
        AjaxResult ajaxResult = booleanLock(testWriteHis1);
        if (!"200".equals(String.valueOf(ajaxResult.get("code")))) {
            log.error("费用已锁定，不能修改");
            return ajaxResult;
        }
        // 获取本次所有 数据
        List<TestWriteHis> allHis = testWriteHisMapper.selectAllByTestWriteHis(testWriteHis1);

        //
        List<TestWriteHis> addWriteHis = new ArrayList<>();
        List<TestWriteHis> updateWriteHis = new ArrayList<>();

        TestWriteHis inTestWriteHis;
        for (TestWriteHis testWrite : testWriteHis) {
            inTestWriteHis = new TestWriteHis();
            inTestWriteHis.setPatientId(testWrite.getPatientId());
            inTestWriteHis.setVisitId(testWrite.getVisitId());
            inTestWriteHis.setItemNo(testWrite.getItemNo());
            inTestWriteHis.setOperId(testWrite.getOperId());
            testWrite.setLocked(0);
            if (allHis.contains(inTestWriteHis)) {
                if ("0.0".equals(testWrite.getAmount()) || "0".equals(testWrite.getAmount())) {
                    testWriteHisMapper.deleteAll(testWriteHis1);
                }
                updateWriteHis.add(testWrite);
            } else {
                addWriteHis.add(testWrite);
            }
        }

        if (CollUtil.isNotEmpty(updateWriteHis)) {
            testWriteHisMapper.batchUpdate(updateWriteHis);
            log.info("修改中间表his:[{}]", JSON.toJSONString(updateWriteHis));
        }
        if (CollUtil.isNotEmpty(addWriteHis)) {
            testWriteHisMapper.batchInsert(addWriteHis);
            log.info("添加中间表his:[{}]", JSON.toJSONString(addWriteHis));
        }

        return AjaxResult.success();
    }


    @Override
    public AjaxResult delWriteHis(List<TestWriteHis> testWriteHis) {
        TestWriteHis testWrit = testWriteHis.get(0);
        AjaxResult ajaxResult = booleanLock(testWrit);
        if (!"200".equals(String.valueOf(ajaxResult.get("code")))) {
            log.error("费用已锁定，不能修改");
            return ajaxResult;
        }

        for (TestWriteHis testWriteHis1 : testWriteHis) {
            testWriteHisMapper.deleteAll(testWriteHis1);
        }
        return AjaxResult.success();
    }


    /**
     * 写入系统物料库
     *
     * @param
     * @return
     */
    @Override
    public Integer addHisMaterial() {
        TimeInterval timer = DateUtil.timer();

        // 查询his 所有药品信息
        List<TestPriceList> priceLists = testPriceListMapper.listPriceListMapper();
        if (CollUtil.isEmpty(priceLists)) {
            return 0;
        }

        // 获取配置表
        Map<String, AtmHisConfig> configMap = this.listHisConfigMap();
        //
        List<AtmHisMaterial> addatmHisMaterials = new ArrayList<>();
        List<AtmHisMaterial> updateMaterialList = new ArrayList<>();
        AtmHisMaterial atmHisMaterial = null;
        AtmHisConfig atmHisConfig = null;

        // 获取itemCode 是否重复
        List<String> itemCodeList = priceLists.stream().map(TestPriceList::getItemCode).collect(Collectors.toList());
        Set<String> itemCodes = atmHisMaterialMapper.itemCodesAll(itemCodeList);

        for (TestPriceList priceList : priceLists) {
            atmHisConfig = configMap.get(priceList.getItemClass());
            if (ObjectUtil.isEmpty(atmHisConfig)) {
                continue;
            }
            atmHisMaterial = new AtmHisMaterial();
            // 如果系统有 则修改

            atmHisMaterial.setItemCode(priceList.getItemCode());
            atmHisMaterial.setItemName(priceList.getItemName());
            atmHisMaterial.setItemSpec(priceList.getItemSpec());
            atmHisMaterial.setUnits(priceList.getUnits());
            atmHisMaterial.setPrice(priceList.getPrice());
            atmHisMaterial.setFeeCategory(atmHisConfig.getFeeCategory());
            atmHisMaterial.setManufacturer(priceList.getMemo());
            atmHisMaterial.setFrequency("");
            atmHisMaterial.setDays(0D);
            atmHisMaterial.setTypeName("");
            atmHisMaterial.setTypeId(priceList.getItemClass());
            atmHisMaterial.setItemClass(atmHisConfig.getMyItemClass());
            atmHisMaterial.setCreateTime(DateUtil.date());
            atmHisMaterial.setUpdateTime(DateUtil.date());
            atmHisMaterial.setGroupName(atmHisConfig.getGroupName());
            atmHisMaterial.setDrugDose(0D);
            atmHisMaterial.setItemNameAbbr("");
            atmHisMaterial.setInvalid(priceList.getInvalid());

            if (ArrayUtils.contains(itemCodes.toArray(), priceList.getItemCode())) {
                updateMaterialList.add(atmHisMaterial);
            } else {
                addatmHisMaterials.add(atmHisMaterial);
            }

        }
        if (CollUtil.isNotEmpty(addatmHisMaterials)) {
            this.batchInsert(addatmHisMaterials);
        }
        if (CollUtil.isNotEmpty(updateMaterialList)) {
            this.batchUpdate(updateMaterialList);
        }

        log.info("写入系统物料库:({} m)", timer.intervalMinute());
        return 1;
    }

    /**
     * 批量修改
     *
     * @param list
     */
    @Async
    void batchUpdate(List<AtmHisMaterial> list) {
        int nums = 1000; // 一次插入200条
        int times = (int) Math.ceil((float) list.size() / nums);// 插入次数
        for (int i = 0; i < times; i++) {
            log.info("=====批量修改第:【{}】次", i);
            if (i == times - 1) {
                atmHisMaterialMapper.batchUpdate(list.subList(i * nums, list.size()));
            } else {
                atmHisMaterialMapper.batchUpdate(list.subList(i * nums, (i + 1) * nums));
            }
        }
    }

    /**
     * 批量插入
     *
     * @param list
     */
    @Async
    void batchInsert(List<AtmHisMaterial> list) {
        int nums = 1000; // 一次插入200条
        int times = (int) Math.ceil((float) list.size() / nums);// 插入次数
        for (int i = 0; i < times; i++) {
            log.info("=====批量插入第:【{}】次", i);
            if (i == times - 1) {
                atmHisMaterialMapper.batchInsert(list.subList(i * nums, list.size()));
            } else {
                atmHisMaterialMapper.batchInsert(list.subList(i * nums, (i + 1) * nums));
            }
        }
    }

    @Override
    public AjaxResult booleanLock(TestWriteHis testWriteHis) {
        log.info("判断是否锁参数值：{}", JSON.toJSONString(testWriteHis));
        testWriteHis.setLocked(1);
        Integer count = testWriteHisMapper.booleanLock(testWriteHis);
        log.info("判断是否锁定值count:{}", count);
        if (count > 0) {
            return AjaxResult.error("数据被锁定，不能同步");
        }
        return AjaxResult.success();
    }


}